package taper.controller;


import javax.swing.SwingUtilities;

import org.apache.log4j.Logger;

import applet.NimbusGui;

import taper.controller.plc.MonitorProcessor;
import util.ErrorMessage;
import util.PropertiesLoader;
import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;
import jssc.SerialPortList;

public class ComPort{
	
	private static final Logger log = Logger.getLogger(ComPort.class);
	
	private String portName ="";
	private int baudRate = SerialPort.BAUDRATE_9600;
	//private int baudRate = SerialPort.BAUDRATE_19200;
	private int dataBits = SerialPort.DATABITS_8;
	private int stopBits = SerialPort.STOPBITS_1;
	private int parity = SerialPort.PARITY_ODD;
	private SerialPort serialPort;
	private static ComPort comPort;
	private static String response = "";
	private boolean isFinishReturn;
	private final int maxRetry = 50;
	
	public static ComPort getInstance() throws Exception{
		if(comPort == null){
			comPort = new ComPort();
		}
		return comPort;
	}
	
	private ComPort() throws Exception{
		
		//boolean isConnect=false;
		boolean isPortAvail = false;
		String[] ports = SerialPortList.getPortNames();
		if (ports.length > 0) {
			for(int i = 0; i < ports.length ; i++){
				if(ports[i].equalsIgnoreCase(PropertiesLoader.getPlcComPort())){
					isPortAvail = true;
					log.info("Com port connected is :"+ports[i]);
					break;
				}
			}
		}

		if(isPortAvail){
		serialPort = new SerialPort(PropertiesLoader.getPlcComPort());
		try {
			if (serialPort.openPort()) {
				if (serialPort.setParams(baudRate, dataBits, stopBits, parity)) {
					 serialPort.addEventListener(new Reader(),
					 SerialPort.MASK_RXCHAR |
					 SerialPort.MASK_RXFLAG |
					 SerialPort.MASK_CTS |
					 SerialPort.MASK_DSR |
					 SerialPort.MASK_RLSD);
					
				} else {
					
					serialPort.closePort();
					log.error("Serial Port :"+PropertiesLoader.getPlcComPort()+" set param fail");
					throw new Exception("Serial Port :"+PropertiesLoader.getPlcComPort()+" set param fail");
				}
			} else {
				log.error("Serial Port :"+PropertiesLoader.getPlcComPort()+" can't open");
				throw new Exception("Serial Port :"+PropertiesLoader.getPlcComPort()+" can't open");
			}
		} catch (SerialPortException e) {
			log.error(e);
			throw e;
		}
		}else{
			log.error("Invalid Com port.Com port: "+PropertiesLoader.getPlcComPort()+" is not connected to the PLC");
			throw new Exception("Invalid Com port.Com port: "+PropertiesLoader.getPlcComPort()+" is not connected to the PLC");
		}
		
	}
	

	

	public String sendMewtocol(String command) throws Exception {
		 synchronized(this) {
			 int waitTimes=0;
				char uniChar = '\r';
				if (command.length() > 0) {
					byte[] buffer;
					try {
						response = "";
						isFinishReturn = false;
						command = command + uniChar;
						log.info("Command Send:"+command);
						serialPort.writeBytes(command.getBytes());
						
						while(!isFinishReturn && waitTimes < maxRetry){
							Thread.sleep(100);
							waitTimes++;
						}
						
						if(response.equalsIgnoreCase("")){
							//ErrorMessage.displayError(ErrorMessage.WARNING_ERROR, true,
							//		"ERROR", "No response from PLC");
							log.error("No response from PLC");
							throw new Exception("No response from PLC");
						}
						
					} catch (Exception ex) {
						log.error("ComPort:sendMewtocol",ex);
						throw ex;
					}
				}
				log.info("Command response:"+response);
				return response;
		 }
	}
	
    private class Reader implements SerialPortEventListener {

        

        public void serialEvent(SerialPortEvent spe) {
            if(spe.isRXCHAR() || spe.isRXFLAG()){
                if(spe.getEventValue() > 0){
                    try {
                    	
                        byte[] buffer = serialPort.readBytes(spe.getEventValue());
                        if(response.equalsIgnoreCase("")){
                        	response = new String(buffer);
                        }else{
                        	response += new String(buffer);
                        }
                        
                        if(response.contains("\r")){
                        	isFinishReturn = true;
            			}
                        
                     }
                    catch (Exception ex) {
                      log.error("Reader:serialEvent");
                    }
                }
            }
           
        }
    }

	public static String getResponse() {
		return response;
	}

	
   

       

}
